﻿using Bouyei.GeoCore.Geometries;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Bouyei.GeoCore.GeoParsers.Wkt
{
    public class GeometryReader:BaseString
    {
        const string bracketContent = @"(?<=\()[^\(\)]*(?=\))";//只是匹配括号内容
        static readonly char[] comma = new char[] { ',' };
        static readonly char[] space = new char[] { ' ' };
        readonly Regex reg;

        public GeoType GeometryType { get; private set; }

        public GeometryReader(string content)
        : base(content)
        {
            reg = new Regex(bracketContent);
        }

        public List<Coordinate[]> Reader()
        {
            int index = Content.IndexOf('(');
            if (index < 0) throw new Exception("not recoginze wkt format");

            string type = Content.Substring(0, index).Trim().ToUpper();
            GeometryType = (GeoType)Enum.Parse(typeof(GeoType), type);

            var matchs = reg.Matches(Content);
            switch (GeometryType)
            {
                case GeoType.POINT:
                    return MultiPoint(matchs);
                case GeoType.LINESTRING:
                    return Linestring(matchs);
                case GeoType.POLYGON:
                    return Polygon(matchs);
                case GeoType.MULTIPOINT:
                    return MultiPoint(matchs);
                case GeoType.MULTILINESTRING:
                    return Linestring(matchs);
                case GeoType.MULTIPOLYGON:
                    return Polygon(matchs);
                case GeoType.GEOMETRYCOLLECTION:
                    throw new Exception("geometryType not supported" + GeometryType);
                default: return null;
            }
        }

        private List<Coordinate[]> Polygon(MatchCollection matchs)
        {
            return MatchCollectionTo(matchs);
        }

        private List<Coordinate[]> MultiPoint(MatchCollection matchs)
        {
            return MatchCollectionTo(matchs);
        }

        private List<Coordinate[]> Linestring(MatchCollection matchs)
        {
            return MatchCollectionTo(matchs);
        }

        private List<Coordinate[]> MatchCollectionTo(MatchCollection matchs)
        {
            List<Coordinate[]> coordinates = new List<Coordinate[]>(matchs.Count);

            foreach (var m in matchs)
            {
                var geo = m.ToString().Split(comma);
                Coordinate[] coords = new Coordinate[geo.Length];

                for (int i = 0; i < coords.Length; ++i)
                {
                    string lonlat = geo[i];

                    var point = lonlat.Trim(' ').Split(space);
                    coords[i] = new Coordinate()
                    {
                        X = double.Parse(point[0]),
                        Y = double.Parse(point[1])
                    };
                }
                coordinates.Add(coords);
            }
            return coordinates;
        }
    }
}
